#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

static int major = 250; // 主设备号 高 12位
static int minor = 0;   // 次设备号 低 20位
static dev_t devno;
static struct class *cls;
static struct device *text_device;

// --- 2. 实现 设备操作 --- 
// 1. open()
// 2. read()
// 3. write()
// 4. lseek()
// 5. close()

static int hello_open (struct inode *inode, struct file *filep)
{
	printk("hello_open \n");
	return 0;
}
static struct file_operations hello_ops=
{
	.open = hello_open,
};
// --- 1. 驱动初始化 --- 
// 1. 获取设备号
// 2. 分配 cdev - register_chrdev_region()
// 3. 初始化cdev - cdev_init()
// 4. 注册 cdev - cdev_add()
static int hello_init(void)
{
	int ret;	
	printk("hello_init");
	devno = MKDEV(major,minor); // 构建 设备号
    // 申请 设备空间
    ret = register_chrdev(major,"hello",&hello_ops);
    // 创建 类
	cls = class_create(THIS_MODULE, "myclass");

	if(IS_ERR(cls))
	{
		unregister_chrdev(major,"hello");
		return -EBUSY;
	}
    // 创建 设备
	test_device = device_create(cls,NULL,devno,NULL,"hello");//mknod /dev/hello
	if(IS_ERR(test_device))
	{
        // 注销 类
		class_destroy(cls);
		unregister_chrdev(major,"hello");
		return -EBUSY;
	}	
	return 0;
}

// --- 3. 驱动注销 --- 
// 1. 注销设备 - cdev_del()
// 2. 释放空间 - unregister_chrdev_region()
static void hello_exit(void)
{
	device_destroy(cls,devno);
	class_destroy(cls);	
	unregister_chrdev(major,"hello");
	printk("hello_exit \n");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
